using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace FwkLight.Domain.Fetching
{
  public interface IFetchingPart<T>: IFetchingPart
  {
    IFetchingPart<R> WhichContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, string alias, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichAlsoContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, string alias, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, string alias);
    IFetchingPart<R> WhichAlsoContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, string alias);
    IFetchingPart<R> WhichContainsEntity<R>(Expression<Func<T, R>> property, string alias);
    IFetchingPart<R> WhichContainsEntity<R>(Expression<Func<T, R>> property, string alias, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichAlsoContainsEntity<R>(Expression<Func<T, R>> property, string alias);
    IFetchingPart<R> WhichAlsoContainsEntity<R>(Expression<Func<T, R>> property, string alias, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> InWhichEveryElementContains<R>(Expression<Func<T, R>> property, string alias);
    IFetchingPart<R> WhichContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichContainsListWithListParent<R>(Expression<Func<T, IEnumerable<R>>> property, Expression<Func<R, IList<T>>> parentProperty);
    IFetchingPart<R> WhichAlsoContainsList<R>(Expression<Func<T, IEnumerable<R>>> property, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichContainsList<R>(Expression<Func<T, IEnumerable<R>>> property);
    IFetchingPart<R> WhichAlsoContainsList<R>(Expression<Func<T, IEnumerable<R>>> property);
    IFetchingPart<R> WhichContainsEntity<R>(Expression<Func<T, R>> property);
    IFetchingPart<R> WhichContainsEntity<R>(Expression<Func<T, R>> property, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichContainsInverseEntity<R>(Expression<Func<T, R>> property);
    IFetchingPart<R> WhichAlsoContainsEntity<R>(Expression<Func<T, R>> property);
    IFetchingPart<R> WhichAlsoContainsEntity<R>(Expression<Func<T, R>> property, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichAlsoContainsEntity<R>(Expression<Func<T, R>> property, Expression<Func<R, IEnumerable<T>>> parentProperty);
    IFetchingPart<R> InWhichEveryElementContains<R>(Expression<Func<T, R>> property);
    IFetchingPart<R> WhichAlsoContainsListFromComponent<S, R>(Expression<Func<T, S>> componentProperty, Expression<Func<S, IEnumerable<R>>> listProperty, string alias);
    IFetchingPart<R> WhichAlsoContainsListFromComponent<S, R>(Expression<Func<T, S>> componentProperty, Expression<Func<S, IEnumerable<R>>> listProperty);
    IFetchingPart<R> WhichAlsoContainsEntityFromComponent<S, R>(Expression<Func<T, S>> componentProperty, Expression<Func<S, R>> property);
    IFetchingPart<R> WhichAlsoContainsListFromComponent<S, R>(Expression<Func<T, S>> componentProperty, Expression<Func<S, IEnumerable<R>>> listProperty, string alias, Expression<Func<R, T>> parentProperty);
    IFetchingPart<R> WhichAlsoContainsListFromComponent<S, R>(Expression<Func<T, S>> componentProperty, Expression<Func<S, IEnumerable<R>>> listProperty, Expression<Func<R, T>> parentProperty);
    IList<IFullSpecification<T>> Specifications { get; set; }
		IList<SpecificationWithOneParam> SpecificationsWithOneParam { get; set; }
    IList<SpecificationWithTwoParams> SpecificationsWithTwoParams { get; set; }
    IList<SpecificationWithThreeParams> SpecificationsWithThreeParams { get; set; }
    IList<SpecificationWithFourParams> SpecificationsWithFourParams { get; set; }
  }

  public interface IFetchingPart
  {
    Type PartType { get; }
    string PropertyName { get; }
    string Alias { get; }
    bool IsRoot { get; }
    IEnumerable<IFetchingPart> EntityChildren { get; }
    IEnumerable<IFetchingPart> ListChildren { get; }
    IEnumerable<IFetchingPart> Children { get; }
    bool IsList { get; }
    IFetchingPart<R> BackTo<R>(string alias);
    IFetchingPart<R> BackTo<R>();
    IFetchingPart<R> SearchInChildren<R>(string alias);
    IList<IFetchingFilter> Filters { get; set; }
    IFetchingPart Parent { get; }
    string ParentPropertyName { get; }
    IList<ISortingPart> SortingList { get; set; }
    bool IsInverse { get; }
    int ChangesCount { get; }
    void IncrementChangesCount();
    void ResetChangesCount();
  }
}